package com.joe.utils;

import org.apache.commons.beanutils.BeanUtilsBean;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Create by joe on 2018/12/27
 */
public class BeanUtils extends org.apache.commons.beanutils.BeanUtils {

    private static final Map<Class<?>, String[]> propNameCache = new HashMap<>();


    public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) {
        PropertyDescriptor[] propDesc2 = BeanUtilsBean.getInstance().getPropertyUtils().getPropertyDescriptors(clazz);
        PropertyDescriptor[] propDesc = new PropertyDescriptor[propDesc2.length - 1];

        int index = 0, i = 0;
        for (; i < propDesc2.length; i++, index++) {
            PropertyDescriptor pd = propDesc2[i];

            if ("class".equals(pd.getName())) {
                index--;
                continue;
            }
            propDesc[index] = propDesc2[i];
        }

        return propDesc;
    }


    public static String[] getPropertyNames(Class<?> clazz) {
        String[] nameArr = propNameCache.get(clazz);

        if (nameArr != null) {
            return nameArr;
        }

        PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
        nameArr = new String[propertyDescriptors.length];

        for (int i = 0; i < propertyDescriptors.length; i++) {
            nameArr[i] = propertyDescriptors[i].getName();
        }

        propNameCache.put(clazz, nameArr);
        return nameArr;
    }

    public static Method getWriteMethod(Object bean, String propName) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        return BeanUtilsBean.getInstance().getPropertyUtils().getPropertyDescriptor(bean, propName).getWriteMethod();
    }

    public static void setValue(Object bean, String propName, Object value) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        getWriteMethod(bean, propName).invoke(bean, value);
    }


}
